#include "comtcp.h"
#include <QDebug>
#include <libmodbus/config.h>

#include "libmodbus/modbus.h"
#include "libmodbus/modbus-private.h"

ComTcp::ComTcp(QString IP, int Port, uint16_t *database, QString serialname, int id, ComMode wormode)
{
    this->IPAddress=IP;
    this->Port=Port;
    this->database=database;
    this->serialname=serialname;
    this->slaveID=id;
    this->workmode=wormode;
}
uint16_t tab_reg[32]={0};
void ComTcp::run()
{
    int server=-1;
    int rc;
    int length,startAddr;
    //char *ip;
    QByteArray ip=this->IPAddress.toLatin1();
    QByteArray serialnm=this->serialname.insert(0,"\\\\.\\").toLatin1();

    mbrtu=modbus_new_rtu(serialnm,9600,'N',8,1);
    modbus_set_slave(mbrtu,this->slaveID);
    modbus_connect(mbrtu);
    struct timeval t;
    t.tv_sec=0;
    t.tv_usec=30000;   //设置modbus超时时间为300毫秒
    modbus_set_response_timeout(mbrtu, &t);
    modbus_set_byte_timeout(mbrtu,&t);
    modbus_set_error_recovery(mbrtu,MODBUS_ERROR_RECOVERY_PROTOCOL);
    mb = modbus_new_tcp(ip,this->Port);//由于是tcp client 连接，在同一程序中相同的端口可以连接多次
    mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
                                    MODBUS_MAX_READ_REGISTERS, 0);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(mb);
        return;
    }
    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
    switch(this->workmode)
    {
    case mode_out:
    {
        server=modbus_tcp_listen(mb,2);
        modbus_tcp_accept(mb,&server);
        for(;;) {
            rc = modbus_receive(mb, query);
            if (rc >= 0) {
                int offset = mb->backend->header_length;
                uint16_t address = (query[offset + 1] << 8) + query[offset + 2];
                int nb = (query[offset + 3] << 8) + query[offset + 4];
                int regs=modbus_read_registers(mbrtu, address, nb, mb_mapping->tab_registers);
                modbus_reply(mb, query, rc, mb_mapping);
            } else {
                modbus_tcp_accept(mb,&server);
                /* Connection closed by the client or server */
//                qDebug()<<"out rc="<<rc;
//                break;
            }
        }
        break;
    }
    case mode_in:
    {
        struct timeval ttcp;
        int tcprc=0;
        modbus_set_slave(mb,this->slaveID);
        int ret=modbus_connect(mb);
        ttcp.tv_sec=3;
        ttcp.tv_usec=2000000;  //设置modbus超时时间为1000毫秒
        modbus_set_response_timeout(mb,&ttcp);
        qDebug()<<ret;
        for(;;) {
            rc = modbus_receive(mbrtu, query);
            if(rc>=0)
            {
                //qDebug()<<"rc"<<rc<<"info"<<query[0]<<query[1]<<query[2]<<query[3]<<query[4]<<query[5];
                //modbus_read_registers(mb,0,32,mb_mapping->tab_registers);
                //modbus_flush(mb);
                startAddr=query[2]<<8|query[3];
                length=query[4]<<8|query[5];
                qDebug()<<"RC"<<rc<<"startAddr"<<startAddr<<"length"<<length;
//                modbus_read_registers(mb,startAddr,length,tab_reg);
//                modbus_read_registers(mb,startAddr,length,tab_reg);
                tcprc=modbus_read_registers(mb,(int)startAddr,(int)length,mb_mapping->tab_registers);
                if(tcprc<0)
                {
                    modbus_connect(mb);
                }
                modbus_reply(mbrtu, query, rc, mb_mapping);
            }
            //modbus_read_registers(mb,0,32,tab_reg);
            qDebug()<<mb_mapping->tab_registers[0]<<mb_mapping->tab_registers[1];
        }
        break;
    }
    }
    modbus_close(mb);
    modbus_free(mb);
    modbus_close(mbrtu);
    modbus_free(mbrtu);
}
